#include "xmlgateway.h"

XmlGateway::XmlGateway(const string& path) : m_filePath(path)
{
    m_doc = new tinyxml2::XMLDocument();
}

XmlGateway::~XmlGateway()
{
    delete m_doc;
}

bool XmlGateway::initXmlFile()
{
#if 1
    // 创建 XML 声明
    XMLDeclaration* decl = m_doc->NewDeclaration("xml version=\"1.0\" encoding=\"utf-8\"");
    m_doc->InsertFirstChild(decl);

    // 创建根元素 <local_gateways>
    XMLElement* root = m_doc->NewElement("local_gateways");
    m_doc->InsertEndChild(root);

    // UDP
    {
        // 创建 Nmea0183和仿Nmea <gateway> 元素
        XMLElement* nmea_gateway = m_doc->NewElement("gateway");
        root->InsertEndChild(nmea_gateway);

        // 添加 <gateway_uid> 元素
        XMLElement* gatewayUid1 = m_doc->NewElement("gateway_uid");
        gatewayUid1->SetText("1575875275");
        nmea_gateway->InsertEndChild(gatewayUid1);

        // 添加 <name> 元素
        XMLElement* name1 = m_doc->NewElement("name");
        name1->SetText("SailingData");
        nmea_gateway->InsertEndChild(name1);

        // 添加 <ip> 元素
        XMLElement* ip1 = m_doc->NewElement("ip");
        nmea_gateway->InsertEndChild(ip1);

        // 添加 <server_ip> 元素
        XMLElement* serverIp1 = m_doc->NewElement("server_ip");
        nmea_gateway->InsertEndChild(serverIp1);

        // 添加 <way_index> 元素
        XMLElement* wayIndex1 = m_doc->NewElement("way_index");
        wayIndex1->SetText("11");
        nmea_gateway->InsertEndChild(wayIndex1);

        // 添加 <mask> 元素
        XMLElement* mask1 = m_doc->NewElement("mask");
        nmea_gateway->InsertEndChild(mask1);

        // 添加 <default_gateway> 元素
        XMLElement* defaultGateway1 = m_doc->NewElement("default_gateway");
        nmea_gateway->InsertEndChild(defaultGateway1);

        // 添加 <way_type> 元素
        XMLElement* wayType1 = m_doc->NewElement("way_type");
        wayType1->SetText("3");
        nmea_gateway->InsertEndChild(wayType1);

        // 添加 <channel_num> 元素
        XMLElement* channelNum = m_doc->NewElement("channel_num");
        channelNum->SetText("8");
        nmea_gateway->InsertEndChild(channelNum);

        // 创建 <channel_info> 元素
        XMLElement* channelInfo = m_doc->NewElement("channel_info");
        channelInfo->SetText("");
        nmea_gateway->InsertEndChild(channelInfo);
    }

    // Modbus
    {
        // 创建 Modbus RTU和Modbus TCP <gateway> 元素
        XMLElement* modbus_gateway = m_doc->NewElement("gateway");
        root->InsertEndChild(modbus_gateway);

        // 添加 <gateway_uid> 元素
        XMLElement* gatewayUid = m_doc->NewElement("gateway_uid");
        gatewayUid->SetText("1575876387");
        modbus_gateway->InsertEndChild(gatewayUid);

        // 添加 <name> 元素
        XMLElement* name1 = m_doc->NewElement("name");
        name1->SetText("EngineData");
        modbus_gateway->InsertEndChild(name1);

        // 添加 <ip> 元素
        XMLElement* ip1 = m_doc->NewElement("ip");
        modbus_gateway->InsertEndChild(ip1);

        // 添加 <server_ip> 元素
        XMLElement* serverIp1 = m_doc->NewElement("server_ip");
        modbus_gateway->InsertEndChild(serverIp1);

        // 添加 <way_index> 元素
        XMLElement* wayIndex1 = m_doc->NewElement("way_index");
        wayIndex1->SetText("11");
        modbus_gateway->InsertEndChild(wayIndex1);

        // 添加 <mask> 元素
        XMLElement* mask1 = m_doc->NewElement("mask");
        modbus_gateway->InsertEndChild(mask1);

        // 添加 <default_gateway> 元素
        XMLElement* defaultGateway1 = m_doc->NewElement("default_gateway");
        modbus_gateway->InsertEndChild(defaultGateway1);

        // 添加 <way_type> 元素
        XMLElement* wayType1 = m_doc->NewElement("way_type");
        wayType1->SetText("3");
        modbus_gateway->InsertEndChild(wayType1);

        // 添加 <channel_num> 元素
        XMLElement* channelNum = m_doc->NewElement("channel_num");
        channelNum->SetText("8");
        modbus_gateway->InsertEndChild(channelNum);

        // 创建 <channel_info> 元素
        XMLElement* channelInfo = m_doc->NewElement("channel_info");
        channelInfo->SetText("");
        modbus_gateway->InsertEndChild(channelInfo);
    }

    // OPC UA
    {
        // 创建 OPC UA <gateway> 元素
        XMLElement* opcua_gateway = m_doc->NewElement("gateway");
        root->InsertEndChild(opcua_gateway);

        // 添加 <gateway_uid> 元素
        XMLElement* gatewayUid = m_doc->NewElement("gateway_uid");
        gatewayUid->SetText("1575876499");
        opcua_gateway->InsertEndChild(gatewayUid);

        // 添加 <name> 元素
        XMLElement* name = m_doc->NewElement("name");
        name->SetText("PSV");
        opcua_gateway->InsertEndChild(name);

        // 添加 <ip> 元素
        XMLElement* ip = m_doc->NewElement("ip");
        opcua_gateway->InsertEndChild(ip);

        // 添加 <server_ip> 元素
        XMLElement* serverIp = m_doc->NewElement("server_ip");
        opcua_gateway->InsertEndChild(serverIp);

        // 添加 <way_index> 元素
        XMLElement* wayIndex = m_doc->NewElement("way_index");
        wayIndex->SetText("16");
        opcua_gateway->InsertEndChild(wayIndex);

        // 添加 <mask> 元素
        XMLElement* mask = m_doc->NewElement("mask");
        opcua_gateway->InsertEndChild(mask);

        // 添加 <default_gateway> 元素
        XMLElement* defaultGateway = m_doc->NewElement("default_gateway");
        opcua_gateway->InsertEndChild(defaultGateway);

        // 添加 <way_type> 元素
        XMLElement* wayType = m_doc->NewElement("way_type");
        wayType->SetText("3");
        opcua_gateway->InsertEndChild(wayType);

        // 添加 <channel_num> 元素
        XMLElement* channelNum = m_doc->NewElement("channel_num");
        channelNum->SetText("8");
        opcua_gateway->InsertEndChild(channelNum);

        // 创建 <channel_info> 元素
        XMLElement* channelInfo = m_doc->NewElement("channel_info");
        channelInfo->SetText("");
        opcua_gateway->InsertEndChild(channelInfo);
    }

    // 保存 XML 文件
    if (m_doc->SaveFile(m_filePath.c_str()) == XML_SUCCESS)
    {
        std::cout << "XML file generated successfully!" << std::endl;
    }
    else
    {
        std::cerr << "Failed to generate XML file!" << std::endl;
    }
#endif
}

bool XmlGateway::loadXML()
{
    if (m_doc->LoadFile(m_filePath.c_str()) != XML_SUCCESS)
    {
        cerr << "Failed to load XML file: " << m_filePath << endl;
        return false;
    }

    return true;
}


void XmlGateway::printXML() const
{
    m_doc->Print();
}

XMLElement *XmlGateway::findGateway(const string &gatewayUid) const
{
    if(m_doc->LoadFile(m_filePath.c_str()) != XML_SUCCESS)
    {
        cerr << "Failed to load XML file: " << m_filePath << endl;
        return nullptr;
    }

    XMLElement* root = m_doc->FirstChildElement("local_gateways");
    if (!root)
    {
        cerr << "Root element not found!" << endl;
        return nullptr;
    }

    XMLElement* gateway = root->FirstChildElement("gateway");
    while (gateway)
    {
        if (gateway->FirstChildElement("gateway_uid") &&
                string(gateway->FirstChildElement("gateway_uid")->GetText()) == gatewayUid)
        {
            return gateway;
        }
        gateway = gateway->NextSiblingElement("gateway");
    }

    cerr << "Gateway with UID " << gatewayUid << " not found!" << endl;
    return nullptr;
}

bool XmlGateway::addChannel(const string &gatewayUid,
                            const string &channelCode, const string &channelType, const string &netMode,
                            const string &ip, const string &port, const string &reply,
                            const string &channelName, const string &status)
{
    // 确保 XML 文件已加载
    if (!loadXML())
    {
        return false;
    }

    // 查找指定的 gateway 节点
    XMLElement* gateway = findGateway(gatewayUid);
    if (!gateway)
    {
        cerr << "Gateway with UID " << gatewayUid << " not found!" << endl;
        return false;
    }

    XMLElement* channelInfo = gateway->FirstChildElement("channel_info");
    if (!channelInfo)
    {
        cerr << "Channel info not found in gateway with UID " << gatewayUid << endl;
        return false;
    }


    XMLElement* channelDetail = m_doc->NewElement("channel_detail");
    if (!channelDetail)
    {
        cerr << "Failed to create channel_detail element!" << endl;
        return false;
    }

    // 添加子节点
    auto addElement = [this, channelDetail](const string& name, const string& value) {
        XMLElement* elem = m_doc->NewElement(name.c_str());
        if (elem)
        {
            elem->SetText(value.c_str());
            channelDetail->InsertEndChild(elem);
        }
        else
        {
            cerr << "Failed to create element: " << name << endl;
            return false;
        }
        return true;
    };

    if (!addElement("channel_code", channelCode) ||
            !addElement("channel_type", channelType) ||
            !addElement("net_mode", netMode) ||
            !addElement("ip", ip) ||
            !addElement("port", port) ||
            !addElement("reply", reply) ||
            !addElement("channel_name", channelName) ||
            !addElement("status", status))
    {
        cerr << "Failed to add channel_detail elements!" << endl;
        return false;
    }

    // 将 channel_detail 添加到 channel_info
    if (!channelInfo->InsertEndChild(channelDetail))
    {
        cerr << "Failed to insert channel_detail into channel_info!" << endl;
        return false;
    }

    cout << "Channel with code " << channelCode << " added successfully." << endl;

    saveXML();

    return true;
}

bool XmlGateway::addChannel(XMLElement *gateway,
                            const string &channelCode, const string &channelType, const string &netMode,
                            const string &ip, const string &port, const string &reply,
                            const string &channelName, const string &status)
{
    // 确保 XML 文件已加载
    if (!loadXML())
    {
        return false;
    }

    if (!gateway)
    {
        cerr << "Invalid gateway element!" << endl;
        return false;
    }

    XMLElement* channelInfo = gateway->FirstChildElement("channel_info");
    if (!channelInfo)
    {
        cerr << "Channel info not found in gateway!" << endl;
        return false;
    }

    XMLElement* channelDetail = m_doc->NewElement("channel_detail");
    if (!channelDetail)
    {
        cerr << "Failed to create channel_detail element!" << endl;
        return false;
    }

    // 添加子节点
    auto addElement = [this, channelDetail](const string& name, const string& value) {
        XMLElement* elem = m_doc->NewElement(name.c_str());
        if (elem)
        {
            elem->SetText(value.c_str());
            channelDetail->InsertEndChild(elem);
        }
        else
        {
            cerr << "Failed to create element: " << name << endl;
            return false;
        }
        return true;
    };

    if (!addElement("channel_code", channelCode) ||
            !addElement("channel_type", channelType) ||
            !addElement("net_mode", netMode) ||
            !addElement("ip", ip) ||
            !addElement("port", port) ||
            !addElement("reply", reply) ||
            !addElement("channel_name", channelName) ||
            !addElement("status", status))
    {
        cerr << "Failed to add channel_detail elements!" << endl;
        return false;
    }

    // 将 channel_detail 添加到 channel_info
    if (!channelInfo->InsertEndChild(channelDetail))
    {
        cerr << "Failed to insert channel_detail into channel_info!" << endl;
        return false;
    }

    cout << "Channel with code " << channelCode << " added successfully." << endl;

    // XMLElement* code = m_doc->NewElement("channel_code");
    // code->SetText(channelCode.c_str());
    // channelDetail->InsertEndChild(code);
    //
    // XMLElement* type = m_doc->NewElement("channel_type");
    // type->SetText(channelType.c_str());
    // channelDetail->InsertEndChild(type);
    //
    // XMLElement* mode = m_doc->NewElement("net_mode");
    // mode->SetText(netMode.c_str());
    // channelDetail->InsertEndChild(mode);
    //
    // XMLElement* ipElem = m_doc->NewElement("ip");
    // ipElem->SetText(ip.c_str());
    // channelDetail->InsertEndChild(ipElem);
    //
    // XMLElement* portElem = m_doc->NewElement("port");
    // portElem->SetText(port.c_str());
    // channelDetail->InsertEndChild(portElem);
    //
    // XMLElement* replyElem = m_doc->NewElement("reply");
    // replyElem->SetText(reply.c_str());
    // channelDetail->InsertEndChild(replyElem);
    //
    // XMLElement* name = m_doc->NewElement("channel_name");
    // name->SetText(channelName.c_str());
    // channelDetail->InsertEndChild(name);
    //
    // XMLElement* statusElem = m_doc->NewElement("status");
    // statusElem->SetText(status.c_str());
    // channelDetail->InsertEndChild(statusElem);
    //
    // gateway->FirstChildElement("channel_info")->InsertEndChild(channelDetail);

    // printf("[%s:%d] %s\n", __FILE__, __LINE__, "addChannel");
    return true;
}

void XmlGateway::deleteChannel(XMLElement *gateway, const string &channelCode)
{
    if (!gateway)
    {
        cerr << "Invalid gateway element!" << endl;
        return;
    }

    XMLElement* channelInfo = gateway->FirstChildElement("channel_info");
    if (!channelInfo)
    {
        cerr << "Channel info not found!" << endl;
        return;
    }

    XMLElement* channelDetail = channelInfo->FirstChildElement("channel_detail");
    while (channelDetail)
    {
        if (channelDetail->FirstChildElement("channel_code") &&
                string(channelDetail->FirstChildElement("channel_code")->GetText()) == channelCode) {
            channelInfo->DeleteChild(channelDetail);
            cout << "Channel with code " << channelCode << " deleted." << endl;
            return;
        }
        channelDetail = channelDetail->NextSiblingElement("channel_detail");
    }

    cerr << "Channel with code " << channelCode << " not found!" << endl;
}

void XmlGateway::updateChannel(XMLElement *gateway, const string &channelCode, const string &newStatus)
{
    if (!gateway)
    {
        cerr << "Invalid gateway element!" << endl;
        return;
    }

    XMLElement* channelInfo = gateway->FirstChildElement("channel_info");
    if (!channelInfo)
    {
        cerr << "Channel info not found!" << endl;
        return;
    }

    XMLElement* channelDetail = channelInfo->FirstChildElement("channel_detail");
    while (channelDetail)
    {
        if (channelDetail->FirstChildElement("channel_code") &&
                string(channelDetail->FirstChildElement("channel_code")->GetText()) == channelCode)
        {
            channelDetail->FirstChildElement("status")->SetText(newStatus.c_str());
            cout << "Channel with code " << channelCode << " updated to status " << newStatus << endl;
            return;
        }
        channelDetail = channelDetail->NextSiblingElement("channel_detail");
    }

    cerr << "Channel with code " << channelCode << " not found!" << endl;
}

void XmlGateway::saveXML(const string &newFilePath)
{
    const char* savePath = newFilePath.empty() ? m_filePath.c_str() : newFilePath.c_str();

    if(m_doc->SaveFile(savePath))
    {
        cerr << "Failed to save XML file: " << savePath << endl;
    }
    else
    {
        cout << "XML file saved successfully: " << savePath << endl;
    }
}
